package org.hamster.common.aggrid.example;

import org.hamster.common.aggrid.AgGridService;
import org.hamster.common.aggrid.model.FilterModel;
import org.hamster.common.aggrid.model.GetRowsRequest;
import org.hamster.common.aggrid.model.GetRowsResponse;
import org.hamster.common.aggrid.model.SortModel;

import java.time.LocalDate;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Example controller showing how to use the ag-Grid service
 */
public class ExampleController {
    
    private final AgGridService<ExampleData> agGridService = new AgGridService<>();
    private final List<ExampleData> allData = generateSampleData();
    
    /**
     * Handle ag-Grid getRows request
     * 
     * @param request The request from ag-Grid
     * @return Response with data for the requested block
     */
    public GetRowsResponse getRows(GetRowsRequest request) {
        // Create filter predicate
        Predicate<ExampleData> filterPredicate = createFilterPredicate(request.getFilterModel());
        
        // Create sort comparator
        java.util.Comparator<ExampleData> sortComparator = createSortComparator(request.getSortModel());
        
        // Get rows using the service
        return agGridService.getRows(request, allData, filterPredicate, sortComparator);
    }
    
    /**
     * Create filter predicate based on filter model
     */
    private Predicate<ExampleData> createFilterPredicate(Map<String, FilterModel> filterModel) {
        if (filterModel == null || filterModel.isEmpty()) {
            return null;
        }
        
        Predicate<ExampleData> predicate = null;
        
        // Create predicate for each field
        for (Map.Entry<String, FilterModel> entry : filterModel.entrySet()) {
            String field = entry.getKey();
            FilterModel model = entry.getValue();
            
            Predicate<ExampleData> fieldPredicate = createFieldPredicate(field, model);
            
            if (predicate == null) {
                predicate = fieldPredicate;
            } else {
                // Combine with AND logic - in a real app you might need to handle OR logic too
                predicate = predicate.and(fieldPredicate);
            }
        }
        
        return predicate;
    }
    
    /**
     * Create predicate for a specific field
     */
    private Predicate<ExampleData> createFieldPredicate(String field, FilterModel model) {
        switch (field) {
            case "name":
                return agGridService.createFilterPredicate(
                    Map.of(field, model), 
                    ExampleData::getName, 
                    field
                );
            case "age":
                return agGridService.createFilterPredicate(
                    Map.of(field, model), 
                    ExampleData::getAge, 
                    field
                );
            case "dateJoined":
                return agGridService.createFilterPredicate(
                    Map.of(field, model), 
                    ExampleData::getDateJoined, 
                    field
                );
            case "salary":
                return agGridService.createFilterPredicate(
                    Map.of(field, model), 
                    ExampleData::getSalary, 
                    field
                );
            default:
                return e -> true; // No filter for unknown fields
        }
    }
    
    /**
     * Create sort comparator based on sort model
     */
    private java.util.Comparator<ExampleData> createSortComparator(Map<String, SortModel> sortModel) {
        if (sortModel == null || sortModel.isEmpty()) {
            return null;
        }
        
        Map<String, java.util.Comparator<ExampleData>> comparators = new HashMap<>();
        comparators.put("id", Comparator.comparing(ExampleData::getId, Comparator.nullsLast(Long::compareTo)));
        comparators.put("name", Comparator.comparing(ExampleData::getName, Comparator.nullsLast(String::compareTo)));
        comparators.put("age", Comparator.comparing(ExampleData::getAge, Comparator.nullsLast(Integer::compareTo)));
        comparators.put("dateJoined", Comparator.comparing(ExampleData::getDateJoined, Comparator.nullsLast(LocalDate::compareTo)));
        comparators.put("salary", Comparator.comparing(ExampleData::getSalary, Comparator.nullsLast(Double::compareTo)));
        
        return agGridService.createSortComparator(sortModel, comparators);
    }
    
    /**
     * Generate sample data for demonstration
     */
    private List<ExampleData> generateSampleData() {
        List<ExampleData> data = new ArrayList<>();
        String[] names = {"John Smith", "Jane Doe", "Bob Johnson", "Alice Williams", "Charlie Brown", 
                          "Diana Miller", "Edward Davis", "Fiona Clark", "George Lewis", "Helen Walker"};
        
        for (int i = 1; i <= 1000; i++) {
            ExampleData item = new ExampleData(
                (long) i,
                names[i % names.length] + " " + (i / names.length + 1),
                20 + (i % 50),
                LocalDate.now().minusDays(i % 365),
                30000.0 + (i % 70000)
            );
            data.add(item);
        }
        
        return data;
    }
}